import { FileChange } from '@/types/modules/editor/types/commit.type';
import { Storage } from './Storage';
import { HistoryApiService, GetFileChangesParams } from './HistoryApiService';
import { DiffUtils, createFileDiff } from '../utils/diff';
import { VirtualFileSystem } from '..';

export interface HistoryServiceConfig {
  projectId: string;
  useRemote: boolean; // 是否使用远程历史记录
  fallbackToLocal: boolean; // 远程失败时是否回退到本地
  syncOnWrite: boolean; // 写入时是否同步到远程
}

/**
 * 混合历史记录服务
 * 支持本地 IndexedDB 和远程 API 的混合使用
 */
export class HybridHistoryService {
  private storage: Storage;
  private apiService: HistoryApiService;
  private config: HistoryServiceConfig;
  private vfs: VirtualFileSystem;

  constructor(config: HistoryServiceConfig) {
    this.config = config;
    this.vfs = VirtualFileSystem.getInstance(this.config.projectId);
    this.storage = this.vfs.storage;
    this.apiService = HistoryApiService.getInstance();
  }

  async init(): Promise<void> {
    await this.storage.init(this.config.projectId);
  }

  /**
   * 获取文件的下一个版本号
   * 优先使用远程，失败时回退到本地
   */
  async getNextVersion(path: string): Promise<number> {
    const { useRemote, fallbackToLocal } = this.config;

    if (useRemote) {
      try {
        const nextVersion = await this.apiService.getNextVersion(this.config.projectId, path);
        return nextVersion;
      } catch (error) {
        console.warn(`[HybridHistoryService] 远程版本号获取失败: ${path}`, error);

        if (fallbackToLocal) {
          console.log(`[HybridHistoryService] 回退到本地版本号计算: ${path}`);
          const localChanges = await this.storage.getChanges(path, { limit: 1000 });
          return localChanges.length + 1;
        } else {
          throw error;
        }
      }
    } else {
      console.log(`[HybridHistoryService] 使用本地版本号计算: ${path}`);
      const localChanges = await this.storage.getChanges(path, { limit: 1000 });
      return localChanges.length + 1;
    }
  }

  /**
   * 🆕 获取指定版本的文件内容
   * 优先使用远程，失败时回退到本地
   */
  async getFileContent(path: string, version?: number): Promise<string | null> {
    const { useRemote, fallbackToLocal } = this.config;
    if (useRemote) {
      try {
        const content = await this.apiService.getFileContent(this.config.projectId, path, version);
        return content;
      } catch (error) {
        if (fallbackToLocal) {
          if (version) {
            return await this.storage.restoreVersion(path, version);
          } else {
            // 获取最新版本
            const localContent = await this.vfs.readFile(path, {
              isCodeMode: true,
            });
            return localContent;
          }
        } else {
          throw error;
        }
      }
    } else {
      console.log(`[HybridHistoryService] 使用本地内容重建: ${path}`);
      if (version) {
        return await this.storage.restoreVersion(path, version);
      } else {
        // 获取最新版本
        const changes = await this.storage.getChanges(path, { limit: 1 });
        if (changes.length > 0) {
          return await this.storage.restoreVersion(path, changes[0].version);
        }
        return null;
      }
    }
  }

  /**
   * 🆕 获取文件的最新内容
   */
  async getLatestFileContent(path: string): Promise<string | null> {
    return this.getFileContent(path);
  }

  /**
   * 获取文件变更记录
   * 优先使用远程，失败时回退到本地
   */
  async getChanges(
    path?: string,
    options?: {
      startTime?: number;
      endTime?: number;
      skip?: number;
      limit?: number;
      sortBy?: string;
      sortOrder?: 'asc' | 'desc';
      excludeDocFiles?: boolean; // 🆕 是否排除 .doc 文件
    },
  ): Promise<FileChange<any>[]> {
    const { useRemote, fallbackToLocal } = this.config;

    if (useRemote) {
      try {
        console.log('[HybridHistoryService] 尝试从远程获取历史记录');

        // 构建请求参数，过滤掉 undefined 值
        const requestParams: any = {
          projectId: this.config.projectId,
          ...options,
        };

        // 只有当 path 不是 undefined 时才添加 path 参数
        if (path !== undefined) {
          requestParams.path = path;
        }

        const response: any = await this.apiService.getFileChanges(requestParams);

        console.log(`[HybridHistoryService] 远程获取成功: ${response.changes.length} 条记录`);
        return response.changes;
      } catch (error) {
        console.warn('[HybridHistoryService] 远程获取失败:', error);

        if (fallbackToLocal) {
          console.log('[HybridHistoryService] 回退到本地历史记录');
          return this.storage.getChanges(path, options);
        } else {
          throw error;
        }
      }
    } else {
      console.log('[HybridHistoryService] 使用本地历史记录');
      return this.storage.getChanges(path, options);
    }
  }

  /**
   * 记录文件变更
   * 根据配置决定是否同步到远程
   */
  async recordChange(
    path: string,
    content: string,
    prevContent: string,
    version: number,
    action: 'add' | 'modify' | 'delete',
    author?: string,
  ): Promise<void> {
    // 始终记录到本地
    const localChange = await this.storage.addChange(
      path,
      content,
      prevContent,
      version,
      action,
      author,
    );
    // 根据配置同步到远程
    if (this.config.syncOnWrite && this.config.useRemote) {
      try {
        let recordParams: any = {
          projectId: this.config.projectId,
          path,
          action,
          author,
        };

        if (action === 'add' || action === 'delete') {
          // 新增或删除文件：发送完整内容
          recordParams.content = content;
          recordParams.previousContent = prevContent;
        } else if (action === 'modify') {
          // 修改文件：根据情况决定发送 diff 还是完整内容

          // 检查是否有有效的上一版本内容
          const hasValidPreviousContent = prevContent && prevContent.trim() !== '';
          const contentChanged = content !== prevContent;

          // 🔥 关键修复：首次版本(version=1)或无有效上一版本时，强制发送完整内容
          const shouldSendFullContent =
            version === 1 ||
            version % 10 === 0 || // 🆕 添加快照版本判断
            !hasValidPreviousContent ||
            !contentChanged;
          if (shouldSendFullContent) {
            // 发送完整内容，让后端创建快照

            recordParams.content = content;
            recordParams.previousContent = prevContent;
          } else {
            // 有有效的上一版本且内容确实改变了，生成 diff
            const fileDiff = createFileDiff(prevContent, content, path);

            // 如果 diff 太大，回退到发送完整内容
            if (!DiffUtils.isDiffSizeReasonable(fileDiff.patch)) {
              recordParams.content = content;
              recordParams.previousContent = prevContent;
            } else {
              recordParams.diff = fileDiff.patch;
              recordParams.contentHash = fileDiff.newHash;
            }
          }
        }

        await this.apiService.recordFileChange(recordParams);
      } catch (error) {
        console.warn(`[HybridHistoryService] 远程同步失败: ${path}`, error);
        // 同步失败不影响本地操作
      }
    }
  }

  /**
   * 获取脏文件列表
   */
  async getDirtyFiles(): Promise<Map<string, any>> {
    if (this.config.useRemote) {
      try {
        return await this.apiService.getDirtyFiles(this.config.projectId);
      } catch (error) {
        console.warn('[HybridHistoryService] 远程获取脏文件失败:', error);

        if (this.config.fallbackToLocal) {
          // 本地没有直接的脏文件概念，返回空
          return new Map();
        } else {
          throw error;
        }
      }
    } else {
      // 本地模式返回空，脏文件由 VFS 管理
      return new Map();
    }
  }

  /**
   * 迁移本地历史记录到远程
   */
  async migrateToRemote(
    onProgress?: (current: number, total: number) => void,
  ): Promise<{ success: number; failed: number; errors: string[] }> {
    console.log('[HybridHistoryService] 开始迁移本地历史记录到远程');

    // 获取所有本地历史记录
    const localChanges = await this.storage.getChanges(undefined, {
      limit: 10000, // 获取大量记录
      sortBy: 'timestamp',
      sortOrder: 'asc', // 按时间正序，保持历史顺序
    });

    if (localChanges.length === 0) {
      console.log('[HybridHistoryService] 没有本地历史记录需要迁移');
      return { success: 0, failed: 0, errors: [] };
    }

    // 转换为 API 格式
    const apiChanges = localChanges.map((change) => ({
      id: change.id?.toString() || '',
      action: change.action,
      path: change.path,
      version: change.version || 1,
      timestamp: change.timestamp,
      diff: {
        before: change.diff?.before,
        after: change.diff?.after,
      },
      author: change.author,
      meta: change.meta,
      projectId: this.config.projectId,
    }));

    // 执行迁移
    return this.apiService.migrateLocalHistory(this.config.projectId, apiChanges, onProgress);
  }

  /**
   * 切换到远程模式
   */
  async switchToRemote(migrateLocal = true): Promise<void> {
    console.log('[HybridHistoryService] 切换到远程模式');

    if (migrateLocal) {
      const result = await this.migrateToRemote();
      console.log('[HybridHistoryService] 迁移结果:', result);
    }

    this.config.useRemote = true;
    this.config.syncOnWrite = true;
    this.config.fallbackToLocal = true;

    console.log('[HybridHistoryService] 已切换到远程模式');
  }

  /**
   * 切换到本地模式
   */
  switchToLocal(): void {
    console.log('[HybridHistoryService] 切换到本地模式');

    this.config.useRemote = false;
    this.config.syncOnWrite = false;
    this.config.fallbackToLocal = false;

    console.log('[HybridHistoryService] 已切换到本地模式');
  }

  /**
   * 获取当前配置
   */
  getConfig(): HistoryServiceConfig {
    return { ...this.config };
  }

  /**
   * 更新配置
   */
  updateConfig(newConfig: Partial<HistoryServiceConfig>): void {
    this.config = { ...this.config, ...newConfig };
    console.log('[HybridHistoryService] 配置已更新:', this.config);
  }
}
